#pragma once
#include "driver/i2c.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#ifdef __cplusplus
extern "C" {
#endif

#define FDC1004_I2C_ADDRESS         0x50    // 7-bit I2C address

// Register addresses
#define FDC1004_MEAS1_MSB           0x00
#define FDC1004_MEAS1_LSB           0x01
#define FDC1004_MEAS2_MSB           0x02
#define FDC1004_MEAS2_LSB           0x03
#define FDC1004_MEAS3_MSB           0x04
#define FDC1004_MEAS3_LSB           0x05
#define FDC1004_MEAS4_MSB           0x06
#define FDC1004_MEAS4_LSB           0x07
#define FDC1004_CONF_MEAS1          0x08
#define FDC1004_CONF_MEAS2          0x09
#define FDC1004_CONF_MEAS3          0x0A
#define FDC1004_CONF_MEAS4          0x0B
#define FDC1004_FDC_CONF            0x0C
#define FDC1004_OFFSET_CAL_CIN1     0x0D
#define FDC1004_OFFSET_CAL_CIN2     0x0E
#define FDC1004_OFFSET_CAL_CIN3     0x0F
#define FDC1004_OFFSET_CAL_CIN4     0x10
#define FDC1004_GAIN_CAL_CIN1       0x11
#define FDC1004_GAIN_CAL_CIN2       0x12
#define FDC1004_GAIN_CAL_CIN3       0x13
#define FDC1004_GAIN_CAL_CIN4       0x14
#define FDC1004_MANUFACTURER_ID     0xFE
#define FDC1004_DEVICE_ID           0xFF

// Measurement configuration
typedef enum {
    FDC1004_CIN1 = 0,
    FDC1004_CIN2 = 1,
    FDC1004_CIN3 = 2,
    FDC1004_CIN4 = 3
} fdc1004_channel_t;

typedef enum {
    FDC1004_RATE_100SPS = 0,
    FDC1004_RATE_200SPS = 1,
    FDC1004_RATE_400SPS = 2
} fdc1004_rate_t;

typedef enum {
    FDC1004_MEASUREMENT_1 = 0,
    FDC1004_MEASUREMENT_2 = 1,
    FDC1004_MEASUREMENT_3 = 2,
    FDC1004_MEASUREMENT_4 = 3
} fdc1004_measurement_t;

typedef enum {
    FDC1004_SINGLE_ENDED = 0,
    FDC1004_DIFFERENTIAL = 1
} fdc1004_measurement_type_t;

// Device configuration structure
typedef struct {
    i2c_port_t i2c_port;
    uint8_t i2c_address;
    gpio_num_t sda_pin;
    gpio_num_t scl_pin;
    uint32_t i2c_freq;
} fdc1004_config_t;

// Measurement result structure
typedef struct {
    float capacitance_pf;    // Capacitance in pF
    int32_t raw_value;       // Raw 24-bit measurement value
    uint8_t measurement_id;  // Measurement ID (1-4)
} fdc1004_measurement_result_t;

// FDC1004 device handle
typedef void* fdc1004_handle_t;

/**
 * @brief Initialize FDC1004 device
 * 
 * @param config Device configuration
 * @return fdc1004_handle_t Device handle or NULL on failure
 */
fdc1004_handle_t fdc1004_init(const fdc1004_config_t *config);

/**
 * @brief Deinitialize FDC1004 device
 * 
 * @param handle Device handle
 */
void fdc1004_deinit(fdc1004_handle_t handle);

/**
 * @brief Reset FDC1004 device
 * 
 * @param handle Device handle
 * @return esp_err_t ESP_OK on success
 */
esp_err_t fdc1004_reset(fdc1004_handle_t handle);

/**
 * @brief Configure a measurement
 * 
 * @param handle Device handle
 * @param measurement_id Measurement ID (1-4)
 * @param positive_channel Positive input channel
 * @param negative_channel Negative input channel (use FDC1004_CIN1 for single-ended with CAPDAC disabled)
 * @param capdac_value CAPDAC value (0-31, each step = 3.125pF)
 * @param rate Measurement rate
 * @return esp_err_t ESP_OK on success
 */
esp_err_t fdc1004_configure_measurement(fdc1004_handle_t handle, 
                                       fdc1004_measurement_t measurement_id,
                                       fdc1004_channel_t positive_channel,
                                       fdc1004_channel_t negative_channel,
                                       uint8_t capdac_value,
                                       fdc1004_rate_t rate);

/**
 * @brief Trigger a single measurement
 * 
 * @param handle Device handle
 * @param measurement_id Measurement ID to trigger
 * @return esp_err_t ESP_OK on success
 */
esp_err_t fdc1004_trigger_measurement(fdc1004_handle_t handle, fdc1004_measurement_t measurement_id);

/**
 * @brief Trigger repeated measurements
 * 
 * @param handle Device handle
 * @param measurement_mask Bitmask of measurements to trigger (bit 0 = measurement 1, etc.)
 * @return esp_err_t ESP_OK on success
 */
esp_err_t fdc1004_trigger_repeated_measurements(fdc1004_handle_t handle, uint8_t measurement_mask);

/**
 * @brief Check if measurement is complete
 * 
 * @param handle Device handle
 * @param measurement_id Measurement ID to check
 * @param is_done Pointer to store completion status
 * @return esp_err_t ESP_OK on success
 */
esp_err_t fdc1004_is_measurement_done(fdc1004_handle_t handle, fdc1004_measurement_t measurement_id, bool *is_done);

/**
 * @brief Read measurement result
 * 
 * @param handle Device handle
 * @param measurement_id Measurement ID to read
 * @param result Pointer to store result
 * @return esp_err_t ESP_OK on success
 */
esp_err_t fdc1004_read_measurement(fdc1004_handle_t handle, fdc1004_measurement_t measurement_id, 
                                  fdc1004_measurement_result_t *result);

/**
 * @brief Set offset calibration for a channel
 * 
 * @param handle Device handle
 * @param channel Channel to calibrate
 * @param offset_pf Offset in pF (-16 to +16 pF)
 * @return esp_err_t ESP_OK on success
 */
esp_err_t fdc1004_set_offset_calibration(fdc1004_handle_t handle, fdc1004_channel_t channel, float offset_pf);

/**
 * @brief Set gain calibration for a channel
 * 
 * @param handle Device handle
 * @param channel Channel to calibrate
 * @param gain Gain factor (0 to 4)
 * @return esp_err_t ESP_OK on success
 */
esp_err_t fdc1004_set_gain_calibration(fdc1004_handle_t handle, fdc1004_channel_t channel, float gain);

/**
 * @brief Read manufacturer ID
 * 
 * @param handle Device handle
 * @param manufacturer_id Pointer to store manufacturer ID
 * @return esp_err_t ESP_OK on success
 */
esp_err_t fdc1004_read_manufacturer_id(fdc1004_handle_t handle, uint16_t *manufacturer_id);

/**
 * @brief Read device ID
 * 
 * @param handle Device handle
 * @param device_id Pointer to store device ID
 * @return esp_err_t ESP_OK on success
 */
esp_err_t fdc1004_read_device_id(fdc1004_handle_t handle, uint16_t *device_id);

#ifdef __cplusplus
}
#endif